import { PlayInfomation } from '@/type';
import CanvasUtils from '@/utils/CanvasUtils';
import PlayController from '@/utils/PlayController';
import RemoveSaveList from '@/utils/RemoveSaveList';
import CanvasEvent from '@/utils/CanvasUtils/CanvasEvent';
import ConfigUtils from './utils/ConfigUtils';
import SplitUtils from './utils/SplitUtils';
import BarUtils from './utils/BarUtils';
import DataUtils from './utils/DataUtils';
import ViewUtils from './utils/ViewUtils';
import PositionUtils from './utils/PositionUtils';
import FpsUtils from '@/utils/FpsUtils';

/** 可视化类 */
export default class Visual {

	/** 画板类 */
	public canvas: CanvasUtils;
	/** 画板事件类 */
	public canvasEvent: CanvasEvent;
	/** 结束事件列表 */
	public OverEvent: RemoveSaveList<VoidFunction>;
	/** 播放控制类 */
	public player: PlayController;
	/** 配置文件系统 */
	public configUtils: ConfigUtils;
	/** 数据管理系统 */
	public dataUtils: DataUtils;
	/** 分割线过渡系统 */
	public splitUtils: SplitUtils;
	/** 数据条过渡系统 */
	public barUtils: BarUtils;
	/** 界面绘制系统 */
	public viewUtils: ViewUtils;
	/** 进度管理系统 */
	public positionUtils: PositionUtils;
	/** 帧数计算系统 */
	public fpsUtils: FpsUtils;
	/** 保存的播放信息 */
	public playInfo: PlayInfomation | null = null;

	/**
	 * 构造函数
	 * @param el 画板元素
	 */
	public constructor(el: HTMLCanvasElement) {
		this.canvas = new CanvasUtils(el);
		this.player = new PlayController(this);
		this.canvasEvent = new CanvasEvent(el);
		this.configUtils = new ConfigUtils();
		this.splitUtils = new SplitUtils(this);
		this.barUtils = new BarUtils(this);
		this.dataUtils = new DataUtils(this);
		this.viewUtils = new ViewUtils(this);
		this.positionUtils = new PositionUtils(this);
		this.OverEvent = new RemoveSaveList<VoidFunction>();
		this.fpsUtils = new FpsUtils();
		this.canvasEvent.Add("resize", () => {
			this.canvas.AutoResize();
		});
		this.BindFpsRefreshTime();
	}

	/** 绑定刷新时间 */
	private BindFpsRefreshTime(): void {
		const { configUtils, fpsUtils } = this;
		const { fpsRefresh } = configUtils.config;
		fpsUtils.RefreshTime.Value = fpsRefresh.Value;
		fpsRefresh.Add(null, () => {
			fpsUtils.RefreshTime.Value = fpsRefresh.Value;
		});
	}

	/** 重新加载 */
	public async Reset() {
		const { playInfo } = this;
		if (playInfo) {
			await this.player.Stop();
			await this.Load(playInfo);
		}
	}

	/**
	 * 加载信息并播放
	 * @param playInfo 播放信息
	 */
	public async Load(playInfo: PlayInfomation): Promise<void> {
		const { canvas, positionUtils, configUtils, barUtils, splitUtils, dataUtils, viewUtils } = this;
		this.playInfo = playInfo;
		canvas.Clear();
		canvas.AutoResize();
		await configUtils.Load(playInfo.path);
		await dataUtils.Load();
		splitUtils.Load();
		barUtils.Load();
		positionUtils.Load();
		viewUtils.Load();
		this.Run();
	}

	/** 开始运行 */
	public Run() { this.player.Run(); }

	/** 停止运行 */
	public async Stop() {
		await this.player.Stop();
		this.OverEvent.List.forEach(({ value: event }) => event());
	}

	/** 更新一次界面 */
	public Update() {
		const { positionUtils, barUtils, splitUtils, fpsUtils } = this;
		const { OnRun, OnLoadingData } = positionUtils;
		if (OnRun) {
			if (OnLoadingData) { this.LoadingData(); }
			positionUtils.Update();
		} else if (!barUtils.HasNext && !splitUtils.HasNext) {
			this.Stop();
		}
		this.DrawAll();
		fpsUtils.Trigger();
	}

	/** 读取数据 */
	private LoadingData() {
		const { dataUtils, barUtils, splitUtils } = this;
		dataUtils.LoadingData();
		barUtils.LoadingData();
		splitUtils.LoadingData();
	}

	/** 绘制全部 */
	private DrawAll() {
		const { canvas, barUtils, splitUtils, viewUtils } = this;
		canvas.Clear();
		barUtils.BeforeDraw();
		splitUtils.BeforeDraw();
		this.DrawBackground();
		viewUtils.Draw();
	}

	/** 绘制背景 */
	private DrawBackground() {
		const { canvas, dataUtils, configUtils } = this;
		const { drawLoadData } = dataUtils;
		const { backgroundColor } = configUtils.config;
		const { backgroundImage } = drawLoadData;
		if (backgroundImage.Value) { canvas.FillBackgroundImage(backgroundImage.Value); }
		else { canvas.FillBackground(backgroundColor.Value); }
	}
}
